package nc.gl.assautoconfig.util;

import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.logging.Logger;
import nc.impl.pub.util.db.InSqlManager;
import nc.itf.bd.pub.IBDMetaDataIDConst;
import nc.itf.gl.pub.IFreevaluePub;
import nc.itf.uap.IUAPQueryBS;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.jdbc.framework.processor.MapProcessor;
import nc.vo.bd.accassitem.AccAssItemVO;
import nc.vo.bd.accchart.AccChartVO;
import nc.vo.bd.account.AccAssVO;
import nc.vo.bd.account.AccountVO;
import nc.vo.fipub.freevalue.Module;
import nc.vo.gateway60.itfs.AccountUtilGL;
import nc.vo.gl.assautoconfig.AccountResultVO;
import nc.vo.gl.assautoconfig.AggAssautoconfigMasterVO;
import nc.vo.gl.assautoconfig.AssautoconfigMasterVO;
import nc.vo.gl.assautoconfig.AssautoconfigSlave0VO;
import nc.vo.gl.glvoucher.AggNVoucherVO;
import nc.vo.gl.glvoucher.NDetailVO;
import nc.vo.gl.glvoucher.NVoucherVO;
import nc.vo.gl.pubvoucher.DetailVO;
import nc.vo.gl.pubvoucher.VoucherVO;
import nc.vo.glcom.ass.AssVO;
import nc.vo.pub.BusinessException;

import nc.vo.vorg.DeptVersionVO;

import nccloud.dto.gl.lightgl.VoucherDetailMDVO;
import nccloud.dto.gl.lightgl.VoucherMDVO;
import nccloud.dto.gl.lightgl.displayformattool.ShowContentCenter;
import nccloud.pubitf.gl.lightgl.voucher.IVoucherWebQryService;
import nccloud.pubitf.uapbd.ref.fiacc.IAccountDefaultModelTreeRefService;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class AssautoconfigUtil {

    public static final String SEP1 = "##";
    public static final String SEP2 = "@@";


    public Map<String, Object> matchCurOrParentAssData(String configtype, String pk_accountingbook, String pk_accasoa, String version, String assid, String sourcePkAccasoa) {
        Map<String, Object> result = new HashMap<>();
        IFreevaluePub iFreevaluePub = NCLocator.getInstance().lookup(IFreevaluePub.class);
        //匹配的时候先判断一下传过来的辅助核算是不是全都有值,如果是全都有值,那么就不需要匹配了
        AssVO[] assVOS = null;//放到这里后面会用
        // boolean allEmpty = true;
        try {
            assVOS = iFreevaluePub.queryAssvosByid(assid, Module.GL);
        } catch (BusinessException e) {
            Logger.error("查询辅助核算失败");
        }
        Map<String, AssVO> assVOMap = Arrays.stream(assVOS).collect(Collectors.toMap(AssVO::getPk_Checktype, AssVO -> AssVO));
        if (StringUtils.isEmpty(configtype)) {//为空的话，则按照会计科目带辅助核算去匹配
            configtype = "1";
        }

        IUAPQueryBS iuapQueryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        //为1的话，是直接根据会计科目找的对应表的辅助核算
        Map<String, Object> masterPks = getMasterPks(configtype, pk_accountingbook, version);
        if (masterPks == null || masterPks.size() == 0) {
            result.put("assid", assid);
            return result;
        }
        String pk_group = (String) masterPks.get("pk_group");
        String sql = " dr=0 and pk_accassoa='" + pk_accasoa + "' and pk_assautoconfigmaster in " + InSqlManager.getInSQLValue((List<String>) masterPks.get("pks")) + " ";
        try {
            Collection<AssautoconfigSlave0VO> slave0VOS = iuapQueryBS.retrieveByClause(AssautoconfigSlave0VO.class, sql);
            String tempAssid = null;
            AssVO[] zassVOS1 = null;
            if (slave0VOS != null && slave0VOS.size() > 0) {
                tempAssid = slave0VOS.toArray(new AssautoconfigSlave0VO[0])[0].getZassid();
                zassVOS1 = iFreevaluePub.queryAssvosByid(tempAssid, Module.GL);
                Map<String, AssVO> zassVOSMap = Arrays.stream(zassVOS1).collect(Collectors.toMap(AssVO::getPk_Checktype, AssVO -> AssVO));
                //判断两个辅助核算项是否一致,不一致则不能匹配了
                Set<String> pk_types = assVOMap.values().stream().filter(AssVO -> AssVO.getPk_Checkvalue() != null && !"~".equals(AssVO.getPk_Checkvalue())).map(AssVO::getPk_Checktype).collect(Collectors.toSet());
                boolean equals = pk_types == null || pk_types.size() == 0 || zassVOSMap.keySet().containsAll(pk_types);
                if (!equals) {
                    result.put("assid", assid);
                    return result;
                }
                Set<String> assPk_checktypes = assVOMap.keySet();
                Optional<AssVO> assVO2 = Arrays.stream(zassVOS1).filter(
                        assVO -> assVO.getPk_Checkvalue() != null && !"~".equals(assVO.getPk_Checkvalue()) && !assPk_checktypes.contains(assVO.getPk_Checktype())).findFirst();
                if (assVO2.isPresent()) {
                    result.put("assid", assid);
                    return result;
                }
                for (String pk_checktype : assVOMap.keySet()) {
                    AssVO srcAssVO = assVOMap.get(pk_checktype);
                    String srcpkCheckvalue = srcAssVO.getPk_Checkvalue();
                    AssVO destAssVO = zassVOSMap.get(pk_checktype);
                    if (destAssVO == null) {
                        continue;
                    }
                    String destpkCheckvalue = destAssVO.getPk_Checkvalue();
                    if (
                            srcpkCheckvalue != null && !"~".equals(srcpkCheckvalue)
                                    && destpkCheckvalue != null && !"~".equals(destpkCheckvalue)
                        //&& !srcpkCheckvalue.equals(destpkCheckvalue)
                    ) {

                        result.put("assid", assid);
                        return result;
                    }
                }
                for (AssVO assVO : assVOS) {
                    if (assVO.getPk_Checkvalue() == null || "~".equals(assVO.getPk_Checkvalue())) {
                        AssVO assVO1 = zassVOSMap.get(assVO.getPk_Checktype());
                        if (assVO1 == null) {
                            continue;
                        }
                        if (assVO1.getPk_Checkvalue() != null && !"~".equals(assVO1.getPk_Checkvalue())) {
                            assVO.setPk_Checkvalue(assVO1.getPk_Checkvalue());
                            assVO.setCheckvaluecode(assVO1.getCheckvaluecode());
                            assVO.setCheckvaluename(assVO1.getCheckvaluename());
                        }
                    }

                }


                assid = iFreevaluePub.getAssID(assVOS, Boolean.TRUE, pk_group, Module.GL);
                if (!isFieldEmpty(assVOS)) {
                    result.put("assid", assid);
                    return result;
                }

            }
        } catch (BusinessException e) {
            Logger.error("匹配出错...");
        }
        result.put("assid", assid);
        return result;


    }


    public Map<String, Object> configtype2(String configtype, String pk_accountingbook, String pk_accasoa, String version, String assid, AssVO[] assVOs, Map<String, Object> result) {
        result = configtype2MatchAssData(configtype, pk_accountingbook, pk_accasoa, version, assid, assVOs, result);
        assid = (String) result.get("assid");
        if (isMatchFlag(assid)) {
            return result;
        }
        AccountVO[] accountVOS = AccountUtilGL.queryByPks(new String[]{pk_accasoa}, version);
        if (accountVOS != null && accountVOS.length != 0) {
            String innercode = accountVOS[0].getInnercode();
            if (StringUtils.isEmpty(innercode) || innercode.length() <= 4) {
                return result;
            }
            List<String> innercodes = new ArrayList<>();
            innercodes.add(innercode.substring(0, 4));
            try {
                List<AccountResultVO> accountResultVOS = QueryAccountInfo.queryParentAccounts(innercodes, accountVOS[0].getPk_currentchart());
                if (accountResultVOS == null || accountResultVOS.size() == 0) {
                    return result;
                }
                while (innercode.length() > 4) {
                    innercode = innercode.substring(0, innercode.length() - 4);
                    String finalInnercode = innercode;
                    Optional<AccountResultVO> first = accountResultVOS.stream().filter(accountResultVO -> finalInnercode.equals(accountResultVO.getInnercode())).findFirst();
                    if (!first.isPresent()) {
                        continue;
                    }
                    String pkAccasoa = first.get().getPk_accasoa();
                    if (StringUtils.isEmpty(pkAccasoa)) {
                        continue;
                    }
                    result = configtype2MatchAssData("2", pk_accountingbook, pkAccasoa, version, assid, assVOs, result);
                    assid = (result == null || result.size() == 0 || !result.containsKey("assid") ? null : (String) result.get("assid"));
                    if (isMatchFlag(assid)) {
                        return result;
                    }
                }


            } catch (BusinessException e) {
                Logger.error("查询会计科目出错");
            }
        }
        return result;
    }

    public Map<String, Object> configtype2MatchAssData(String configtype, String pk_accountingbook, String pk_accasoa, String version, String assid, AssVO[] assVOs, Map<String, Object> result) {

        IUAPQueryBS iuapQueryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        Map<String, Object> masterPks = getMasterPks(configtype, pk_accountingbook, version);
        if (masterPks == null || masterPks.size() == 0) {
            result.put("assid", assid);
            return result;
        }
        String pk_group = (String) masterPks.get("pk_group");
        String sql = " dr=0 and pk_accassoa='" + pk_accasoa + "' and pk_assautoconfigmaster in " + InSqlManager.getInSQLValue((List<String>) masterPks.get("pks")) + " ";
        Collection<AssautoconfigSlave0VO> slave0VOS2 = null;
        IFreevaluePub iFreevaluePub = NCLocator.getInstance().lookup(IFreevaluePub.class);
        Map<String, AssVO> assVOMap = Arrays.stream(assVOs).collect(Collectors.toMap(AssVO::getPk_Checktype, AssVO -> AssVO));
        try {
            slave0VOS2 = iuapQueryBS.retrieveByClause(AssautoconfigSlave0VO.class, sql);

            if (slave0VOS2 == null || slave0VOS2.size() == 0) {
                result.put("assid", assid);
                return result;
            }
            slave0VOS2 = Arrays.stream(sortRowno(slave0VOS2.toArray(new AssautoconfigSlave0VO[0]))).toList();
            //传过来的辅助核算内容，这里就是弹框里看得到辅助核算
            out:
            for (AssautoconfigSlave0VO slave0VO : slave0VOS2) {
                String zassid = slave0VO.getZassid();
                AssVO[] zassVOS = new AssVO[0];
                try {
                    zassVOS = iFreevaluePub.queryAssvosByid(zassid, Module.GL);
                } catch (BusinessException e) {
                    Logger.error("查询数据出错");
                }
                //匹配的辅助核算项是分录的子集且值相等,则完全匹配
                Map<String, AssVO> zassVOSMap = Arrays.stream(zassVOS).filter(assVO -> assVO.getPk_Checkvalue() != null && !"~".equals(assVO.getPk_Checkvalue())).collect(Collectors.toMap(AssVO::getPk_Checktype, AssVO -> AssVO));
                boolean matchFlag = false;
                if (assVOMap.keySet().containsAll(zassVOSMap.keySet())) {
                    Set<String> srcAssValues = assVOMap.values().stream().map(AssVO -> AssVO.getPk_Checktype() + AssVO.getPk_Checkvalue()).collect(Collectors.toSet());
                    Set<String> destAssValues = zassVOSMap.values().stream().map(AssVO -> AssVO.getPk_Checktype() + AssVO.getPk_Checkvalue()).collect(Collectors.toSet());
                    if (srcAssValues.containsAll(destAssValues)) {
                        matchFlag = true;
                    }
                    //找父级的辅助核算项的值去和分录的匹配
                    if (!matchFlag) {

                        for (AssVO assVO : assVOs) {

                            String srcpkChecktype = assVO.getPk_Checktype();
                            String srcpkCheckvalue = assVO.getPk_Checkvalue();
                            AssVO destAssVO = zassVOSMap.get(srcpkChecktype);
                            if (destAssVO == null) {
                                continue;
                            }
                            String destpkCheckvalue = destAssVO.getPk_Checkvalue();
                            if (srcpkCheckvalue != null && !"~".equals(srcpkCheckvalue)) {
                                if (srcpkCheckvalue != null && !"~".equals(srcpkCheckvalue)) {
                                    if (!destpkCheckvalue.equals(srcpkCheckvalue)) {
                                        //找父级
                                        int contain = QueryDocParentInfo.contain(srcpkChecktype, destpkCheckvalue, srcpkCheckvalue);
                                        if (contain == -1) {
                                            continue out;
                                        }

                                    }
                                }
                            } else {
                                if (destpkCheckvalue != null && !"~".equals(destpkCheckvalue)) {
                                    continue out;
                                }

                            }

                        }

                    }
                }


                String fassid = slave0VO.getFassid();
                AssVO[] fassVOS = iFreevaluePub.queryAssvosByid(fassid, Module.GL);
                Map<String, AssVO> fassVOMap = Arrays.stream(fassVOS).collect(Collectors.toMap(AssVO::getPk_Checktype, AssVO -> AssVO));
                for (String pk_checktype : assVOMap.keySet()) {
                    AssVO srcAssVO = assVOMap.get(pk_checktype);
                    String srcpkCheckvalue = srcAssVO.getPk_Checkvalue();
                    AssVO destAssVO = fassVOMap.get(pk_checktype);
                    if (destAssVO == null) {
                        continue;
                    }
                    String destpkCheckvalue = destAssVO.getPk_Checkvalue();

                    if (srcpkCheckvalue != null && !"~".equals(srcpkCheckvalue)
                            && destpkCheckvalue != null && !"~".equals(destpkCheckvalue)
                            && !srcpkCheckvalue.equals(destpkCheckvalue)) {
                        continue out;
                    }
                }
                for (AssVO zassVO : assVOs) {
                    if (StringUtils.isEmpty(zassVO.getPk_Checkvalue()) || "~".equals(zassVO.getPk_Checkvalue())) {
                        AssVO fassVO = fassVOMap.get(zassVO.getPk_Checktype());
                        if (fassVO == null) {
                            continue;
                        }
                        if (StringUtils.isNotEmpty(fassVO.getPk_Checkvalue()) && !"~".equals(fassVO.getPk_Checkvalue())
                        ) {
                            if (!isFieldEmpty(assVOs)) {
                                break out;
                            }
                            zassVO.setPk_Checkvalue(fassVO.getPk_Checkvalue());
                            zassVO.setCheckvaluecode(fassVO.getCheckvaluecode());
                            zassVO.setCheckvaluename(fassVO.getCheckvaluename());
                        }
                    }
                }
            }
        } catch (BusinessException e) {
            Logger.error("查询数据出错");
        }
        try {
            assid = iFreevaluePub.getAssID(assVOs, Boolean.TRUE, pk_group, Module.GL);
        } catch (BusinessException e) {
            Logger.error("查询数据出错");
        }
        result.put("assid", assid);
        return result;
    }

    public Map<String, Object> matchAssData(String configtype, String pk_accountingbook, String pk_accasoa, String version, String assid) {
        //如果都有值,不需要匹配了
        Map<String, Object> result = new HashMap<>();
        if (isMatchFlag(assid)) {
            result.put("assid", assid);
            return result;
        }
        //根据最新日期查询会计科目版本,因为这里的version传过来很可能是业务日期,需要把业务日期转换为对应的会计科目版本
        AccChartVO accChartVO = ((IAccountDefaultModelTreeRefService) NCLocator.getInstance().lookup(IAccountDefaultModelTreeRefService.class)).getPrevCondition(pk_accountingbook, version.substring(0, 10), true);
        if (accChartVO == null) {
            result.put("assid", assid);
            return result;
        }
        version = accChartVO.getBeginperiod();
        //0.会计科目没有辅助核算,则不匹配 start
        AccountVO[] accountVOS = AccountUtilGL.queryByPks(new String[]{pk_accasoa}, version);
        if (accountVOS == null || accountVOS.length == 0||accountVOS[0]==null) {
            return result;
        }
        AccAssVO[] accass = accountVOS[0].getAccass();
        if (accass == null || accass.length == 0) {
            return result;
        }
        IVoucherWebQryService webQryService = NCLocator.getInstance().lookup(IVoucherWebQryService.class);
        AccAssItemVO[] accAssItemVOS = null;
        try {
            accAssItemVOS = webQryService.queryAssItemByAsoaPk(pk_accasoa, version);
        } catch (BusinessException e) {
            //throw new RuntimeException(e);
        }
        if (accAssItemVOS == null || accAssItemVOS.length == 0) {
            return result;
        }
        //0.会计科目没有辅助核算,则不匹配 end
        //补充:如果会计科目存在辅助核算项,但是没有空的辅助核算项的assid,那么应该生成一个 start
        IFreevaluePub iFreevaluePub = NCLocator.getInstance().lookup(IFreevaluePub.class);
        if (StringUtils.isEmpty(assid)) {
            List<AssVO> objects = new ArrayList<>();
            for (AccAssItemVO accAssItemVO : accAssItemVOS) {
                AssVO assVO = new AssVO();
                assVO.setPk_Checktype(accAssItemVO.getPk_accassitem());
                assVO.setChecktypecode(accAssItemVO.getCode());
                assVO.setChecktypename(accAssItemVO.getName());
                assVO.setM_classid(accAssItemVO.getClassid());
                objects.add(assVO);
            }

            try {
                assid = iFreevaluePub.getAssID(objects.toArray(new AssVO[0]), Boolean.TRUE, InvocationInfoProxy.getInstance().getGroupId(), Module.GL);

                //assid = iFreevaluePub.getAssID_RequiresNew(objects.toArray(new AssVO[0]), Boolean.TRUE, null, null, Module.GL);
            } catch (BusinessException e) {
                //throw new RuntimeException(e);
            }
        }
        //补充:如果会计科目存在辅助核算项,但是没有空的辅助核算项的assid,那么应该生成一个 end

        String sourcePkAccasoa = pk_accasoa;
        //1.先走会计科目带辅助的当前科目及父级科目  start
        result = matchCurOrParentAssData(configtype, pk_accountingbook, pk_accasoa, version, assid, sourcePkAccasoa);
        if (result != null && result.size() > 0) {
            assid = (String) result.get("assid");
        }
        if (isMatchFlag(assid)) {
            return result;
        }
        //走到这里需要查当前科目的父级及以上,直到匹配到或者走完没有匹配到
        if (accountVOS != null && accountVOS.length != 0) {
            String innercode = accountVOS[0].getInnercode();
//            if (StringUtils.isEmpty(innercode) || innercode.length() <= 4) {
//                return result;
//            }
            List<String> innercodes = new ArrayList<>();
            innercodes.add(innercode.substring(0, 4));
            try {
                List<AccountResultVO> accountResultVOS = QueryAccountInfo.queryParentAccounts(innercodes, accountVOS[0].getPk_currentchart());
                if (accountResultVOS == null || accountResultVOS.size() == 0) {
                    return result;
                }
                while (innercode.length() > 4) {
                    innercode = innercode.substring(0, innercode.length() - 4);
                    String finalInnercode = innercode;
                    Optional<AccountResultVO> first = accountResultVOS.stream().filter(accountResultVO -> finalInnercode.equals(accountResultVO.getInnercode())).findFirst();
                    if (!first.isPresent()) {
                        continue;
                    }
                    String pkAccasoa = first.get().getPk_accasoa();
                    if (StringUtils.isEmpty(pkAccasoa)) {
                        continue;
                    }
                    result = matchCurOrParentAssData(configtype, pk_accountingbook, pkAccasoa, version, assid, sourcePkAccasoa);
                    assid = (result == null || result.size() == 0 || !result.containsKey("assid") ? null : (String) result.get("assid"));
                    if (isMatchFlag(assid)) {
                        return result;
                    }

                }
            } catch (BusinessException e) {
                Logger.error("查询会计科目出错");
            }
        }
        //1.先走会计科目带辅助的当前科目及父级科目  end

        //2.辅助带辅助,去匹配当前科目的辅助带辅助和父级会计科目的辅助带辅助 start
        AssVO[] assVOs = new AssVO[0];
        try {
            assVOs = iFreevaluePub.queryAssvosByid(assid, Module.GL);
        } catch (BusinessException e) {
            //throw new RuntimeException(e);
        }
        if (isAllEmpty(assVOs)) {
            result.put("assid", assid);
            return result;
        }
        result = this.configtype2("2", pk_accountingbook, sourcePkAccasoa, version, assid, assVOs, result);
        //2.辅助带辅助,去匹配当前科目的辅助带辅助和父级会计科目的辅助带辅助 end
        return result;
    }

    /**
     * @param assid
     * @return
     */
    private boolean isMatchFlag(String assid) {
        boolean matchflag = false;
        if (StringUtils.isNotEmpty(assid)) {
            IFreevaluePub iFreevaluePub = NCLocator.getInstance().lookup(IFreevaluePub.class);
            AssVO[] assVOS = new AssVO[0];
            try {
                assVOS = iFreevaluePub.queryAssvosByid(assid, Module.GL);
            } catch (BusinessException e) {
                Logger.error("查询辅助核算ID出错");
            }
            matchflag = !isFieldEmpty(assVOS);
        }
        return matchflag;

    }

    public Map<String, Object> showAss(Map<String, Object> params) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        try {
            Map<String, Object> assData = matchAssData(params.get("configtype").toString(), params.get("pk_accountingbook").toString(), params.get("pk_accasoa").toString(), params.get("version").toString(), params.get("assid") == null ? null : params.get("assid").toString());
            AssVO[] assVOs = null;
            List<Object> objects = new ArrayList<>();
            assVOs = NCLocator.getInstance().lookup(IFreevaluePub.class).queryAssvosByid(assData.get("assid") == null ? null : assData.get("assid").toString(), Module.GL);
            if (assVOs != null) {
                for (AssVO assVO : assVOs) {
                    if (StringUtils.isEmpty(assVO.getM_pk_vid())||"~".equals(assVO.getM_pk_vid())){
                        String specialAssValue = getSpecialAssValue(assVO.getM_classid(), assVO.getPk_Checkvalue());
                        assVO.setM_pk_vid(specialAssValue);
                    }
                    Object[] ary = new Object[8];
                    ary[0] = assVO.getM_classid();
                    ary[1] = assVO.m_pk_checktype;
                    ary[2] = assVO.m_checktypecode;
                    ary[3] = assVO.m_checktypename;
                    ary[4] = assVO.getPk_Checkvalue();
                    ary[5] = assVO.m_checkvaluecode;
                    ary[6] = assVO.m_checkvaluename;
                    ary[7] = assVO.getM_pk_vid();
                    objects.add(ary);
                }
            }
            resultMap.put("ass", objects);
            resultMap.put("assVO", assVOs);
            resultMap.put("assid", assData.get("assid") == null ? null : assData.get("assid").toString());
            resultMap.put("display", ShowContentCenter.getAssShowName(assVOs));
        } catch (BusinessException e) {
            Logger.error("查询辅助核算出错。。。");
        }
        return resultMap;

    }
    //特殊
    private String getSpecialAssValue(String classid,String pk){
        if (StringUtils.isEmpty(classid)||StringUtils.isEmpty(pk)){
            return null;
        }
        IUAPQueryBS iuapQueryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        if (IBDMetaDataIDConst.DEPT.equals(classid)){
            try {
                Collection<DeptVersionVO> collection = iuapQueryBS.retrieveByClause(DeptVersionVO.class, " pk_dept='" + pk + "' ");
                if (collection==null||collection.size()==0){
                    return null;
                }
                return collection.toArray(new DeptVersionVO[0])[0].getPk_vid();
            } catch (BusinessException e) {
                //throw new RuntimeException(e);
            }

        }
        return  null;


    }

    public AggNVoucherVO beforeSaveAutoMatchAssData(AggNVoucherVO voucherVO) {
        if (voucherVO == null) {
            return voucherVO;
        }
        NVoucherVO parentVO = voucherVO.getParentVO();
        if (parentVO == null) {
            return voucherVO;
        }
        NDetailVO[] childrenVO = voucherVO.getChildrenVO();
        if (childrenVO == null || childrenVO.length == 0) {
            return voucherVO;
        }
        voucherVO.setChildrenVO(matchAss(parentVO.getPk_accountingbook(), parentVO.getPrepareddate().toString(), childrenVO));
        return voucherVO;

    }

    public VoucherVO beforeSaveAutoMatchAssData(VoucherVO voucherVO) {
        if (voucherVO == null) {
            return voucherVO;
        }
        DetailVO[] details = voucherVO.getDetails();
        if (details == null || details.length == 0) {
            return voucherVO;
        }
        voucherVO.setDetails(matchAss(voucherVO.getPk_accountingbook(), voucherVO.getPrepareddate().toString(), voucherVO.getDetails()));
        return voucherVO;

    }

    public List<VoucherMDVO> beforeSaveAutoMatchAssData(List<VoucherMDVO> voucherVOs) {
        if (voucherVOs == null || voucherVOs.size() == 0) {
            return voucherVOs;
        }
        for (VoucherMDVO voucherVO : voucherVOs) {
            VoucherDetailMDVO[] detailMDVOs = voucherVO.getDetailMDVOs();
            if (detailMDVOs == null || detailMDVOs.length == 0) {
                continue;
            }
            matchAss(voucherVO.getPk_accountingbook(), voucherVO.getPrepareddate().toString(), voucherVO.getDetailMDVOs());

        }
//        DetailVO[] details = voucherVO.getDetails();
//        if (details == null || details.length == 0) {
//            return voucherVO;
//        }
//        voucherVO.setDetails(matchAss(voucherVO.getPk_accountingbook(), voucherVO.getPrepareddate().toString(), voucherVO.getDetails()));
//        return voucherVO;
        return null;

    }

    public DetailVO[] matchAss(String pk_accountingbook, String version, DetailVO[] details) {
        if (details == null || details.length == 0) {
            return details;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("configtype", "1");
        params.put("pk_accountingbook", pk_accountingbook);
        params.put("version", version);
        for (DetailVO detailVO : details) {
            String pkAccasoa = detailVO.getPk_accasoa();
            String assid = detailVO.getAssid();
            params.put("pk_accasoa", pkAccasoa);
            params.put("assid", assid);
            Map<String, Object> assData = showAss(params);
            if (assData != null) {
                Object assid1 = assData.get("assid");
                if (assid1 != null) {
                    detailVO.setAssid(assid1.toString());
                    Object assVO = assData.get("assVO");
                    if (assVO != null) {
                        detailVO.setAss((AssVO[]) assVO);
                    }

                }
            }
        }
        return details;

    }

    public VoucherDetailMDVO[] matchAss(String pk_accountingbook, String version, VoucherDetailMDVO[] details) {
        if (details == null || details.length == 0) {
            return details;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("configtype", "1");
        params.put("pk_accountingbook", pk_accountingbook);
        params.put("version", version);
        for (VoucherDetailMDVO detailVO : details) {
            String pkAccasoa = detailVO.getPk_accasoa();
            String assid = detailVO.getAssid();
            params.put("pk_accasoa", pkAccasoa);
            params.put("assid", assid);
            Map<String, Object> assData = showAss(params);
            if (assData != null) {
                Object assid1 = assData.get("assid");
                if (assid1 != null) {
                    detailVO.setAssid(assid1.toString());
                    Object assVO = assData.get("assVO");
                    if (assVO != null) {
                        detailVO.setAss((AssVO[]) assVO);
                    }

                }
            }
        }
        return details;

    }

    public NDetailVO[] matchAss(String pk_accountingbook, String version, NDetailVO[] details) {
        if (details == null || details.length == 0) {
            return details;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("configtype", "1");
        params.put("pk_accountingbook", pk_accountingbook);
        params.put("version", version);
        for (NDetailVO detailVO : details) {
            String pkAccasoa = detailVO.getPk_accasoa();
            String assid = detailVO.getAssid();
            params.put("pk_accasoa", pkAccasoa);
            params.put("assid", assid);
            Map<String, Object> assData = showAss(params);
            if (assData != null) {
                Object assid1 = assData.get("assid");
                if (assid1 != null) {
                    detailVO.setAssid(assid1.toString());
                    Object assVO = assData.get("assVO");
                    if (assVO != null) {
                        detailVO.setAssvos((AssVO[]) assVO);
                    }

                }
            }
        }
        return details;

    }

    public boolean isFieldEmpty(AssVO[] assVOs) {
        return Arrays.stream(assVOs)
                .anyMatch(vo -> vo.getPk_Checkvalue() == null || vo.getPk_Checkvalue().isEmpty() || "~".equals(vo.getPk_Checkvalue()));

    }

    public boolean isAllEmpty(AssVO[] assVOs) {
        return Arrays.stream(assVOs)
                .allMatch(vo -> vo.getPk_Checkvalue() == null || vo.getPk_Checkvalue().isEmpty() || "~".equals(vo.getPk_Checkvalue()));

    }

    public static AggAssautoconfigMasterVO[] sortRowno(AggAssautoconfigMasterVO[] masterVOs) {
        if (masterVOs == null || masterVOs.length == 0) {
            return masterVOs;
        }
        for (AggAssautoconfigMasterVO assautoconfigMasterVO : masterVOs) {
            sortRowno(assautoconfigMasterVO);
        }
        return masterVOs;

    }

    public static AggAssautoconfigMasterVO[] sortRowno(AggAssautoconfigMasterVO[] masterVOs, boolean filterDr) {
        if (masterVOs == null || masterVOs.length == 0) {
            return masterVOs;
        }
        for (AggAssautoconfigMasterVO aggvo : masterVOs) {
            if (filterDr) {
                AssautoconfigSlave0VO[] children = (AssautoconfigSlave0VO[]) aggvo.getChildren(AssautoconfigSlave0VO.class);
                if (children != null && children.length > 0) {
                    List<AssautoconfigSlave0VO> result = Arrays.stream(children)
                            .filter(assautoconfigSlave0VO -> assautoconfigSlave0VO.getDr() == null || assautoconfigSlave0VO.getDr() == 0).collect(Collectors.toList());
                    aggvo.setChildrenVO(result == null || result.size() == 0 ? null : result.toArray(new AssautoconfigSlave0VO[0]));
                }
            }
            sortRowno(aggvo);
        }
        return masterVOs;

    }

    public static AggAssautoconfigMasterVO sortRowno(AggAssautoconfigMasterVO masterVO) {
        if (masterVO == null) {
            return masterVO;
        }
        AssautoconfigSlave0VO[] children = (AssautoconfigSlave0VO[]) masterVO.getChildren(AssautoconfigSlave0VO.class);
        sortRowno(children);
        return masterVO;
    }

    public static AssautoconfigSlave0VO[] sortRowno(AssautoconfigSlave0VO[] children) {
        if (children == null || children.length == 0) {
            return children;
        }
        final int sortType = 1;
        Arrays.sort(children, new Comparator<AssautoconfigSlave0VO>() {
            @Override
            public int compare(AssautoconfigSlave0VO o1, AssautoconfigSlave0VO o2) {
                if (Double.parseDouble(o1.getRowno()) > Double.parseDouble(o2.getRowno())) {
                    return 1 * sortType;
                } else if (Double.parseDouble(o1.getRowno()) < Double.parseDouble(o2.getRowno())) {
                    return -1 * sortType;
                }
                return 0;
            }

        });
        return children;

    }

    public static Map<String, Object> getMasterPks(String configtype, String pk_accountingbook, String version) {
        String whereSql = " dr=0 and configtype='" + configtype + "' and pk_accountingbook='" + pk_accountingbook + "' and asoaversion='" + version + "'";
        IUAPQueryBS iuapQueryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        Collection<AssautoconfigMasterVO> collection = null;
        try {
            collection = iuapQueryBS.retrieveByClause(AssautoconfigMasterVO.class, whereSql);
        } catch (BusinessException e) {
            Logger.error("查询出错...");
        }
        if (collection == null || collection.size() == 0) {
            return null;
        }
        String pkGroup = collection.toArray(new AssautoconfigMasterVO[0])[0].getPk_group();
        List<String> list = collection.stream().map(AssautoconfigMasterVO::getPk_assautoconfigmaster).toList();
        Map<String, Object> map = new HashMap<>();
        map.put("pk_group", pkGroup);
        map.put("pks", list);
        return map;


    }

    public String getFathePk(String pk_accasoa) throws BusinessException {
        //查询该编码所有父级编码
        String sql = " select  pk_accasoa from bd_accasoa where pk_account in (Select pk_account from bd_account \r\n" +
                "                       start with  pk_account=(select pk_account from bd_accasoa where pk_accasoa='"+pk_accasoa+"')\r\n" +
                "                       connect by prior pid=pk_account) and dr =0";
        IUAPQueryBS iuapQueryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        List<Map<String, Object>> freecalueList = (List<Map<String, Object>>) iuapQueryBS.executeQuery(sql, new MapListProcessor());
        StringBuilder sb = new StringBuilder();
        for (Map<String, Object> map : freecalueList) {
            if (map.containsKey("pk_accasoa")) {
                Object value = map.get("pk_accasoa");
                // 转换为字符串并添加到StringBuilder
                sb.append("'").append(value.toString()).append("',");
            }
        }

        // 移除最后一个逗号
        if (sb.length() > 0) {
            sb.setLength(sb.length() - 1);
        }
        //父级编码整理为String












        return sb.toString();

    }

    public String getassid(String pk_defdoc,String pk_accasoa) throws BusinessException {
        //根据当前pk_defdoc 查询父类是否在自动配置表中有记录，  父类在辅助核算表中

        String sql = "	SELECT freevalueid,\r\n" +
                "    CASE\r\n" +
                "        WHEN INSTR(typevalue1, '1001A210000000000RIH') > 0 THEN SUBSTR(typevalue1, INSTR(typevalue1, '1001A210000000000RIH') + LENGTH('1001A210000000000RIH'))\r\n" +
                "        WHEN INSTR(typevalue2, '1001A210000000000RIH') > 0 THEN SUBSTR(typevalue2, INSTR(typevalue2, '1001A210000000000RIH') + LENGTH('1001A210000000000RIH'))\r\n" +
                "        WHEN INSTR(typevalue3, '1001A210000000000RIH') > 0 THEN SUBSTR(typevalue3, INSTR(typevalue3, '1001A210000000000RIH') + LENGTH('1001A210000000000RIH'))\r\n" +
                "        WHEN INSTR(typevalue4, '1001A210000000000RIH') > 0 THEN SUBSTR(typevalue4, INSTR(typevalue4, '1001A210000000000RIH') + LENGTH('1001A210000000000RIH'))\r\n" +
                "        WHEN INSTR(typevalue5, '1001A210000000000RIH') > 0 THEN SUBSTR(typevalue5, INSTR(typevalue5, '1001A210000000000RIH') + LENGTH('1001A210000000000RIH'))\r\n" +
                "        WHEN INSTR(typevalue6, '1001A210000000000RIH') > 0 THEN SUBSTR(typevalue6, INSTR(typevalue6, '1001A210000000000RIH') + LENGTH('1001A210000000000RIH'))\r\n" +
                "        WHEN INSTR(typevalue7, '1001A210000000000RIH') > 0 THEN SUBSTR(typevalue7, INSTR(typevalue7, '1001A210000000000RIH') + LENGTH('1001A210000000000RIH'))\r\n" +
                "        WHEN INSTR(typevalue8, '1001A210000000000RIH') > 0 THEN SUBSTR(typevalue8, INSTR(typevalue8, '1001A210000000000RIH') + LENGTH('1001A210000000000RIH'))\r\n" +
                "        WHEN INSTR(typevalue9, '1001A210000000000RIH') > 0 THEN SUBSTR(typevalue9, INSTR(typevalue9, '1001A210000000000RIH') + LENGTH('1001A210000000000RIH'))\r\n" +
                "        ELSE NULL\r\n" +
                "    END AS pk_defdoc\r\n" +
                "FROM gl_freevalue\r\n" +
                "WHERE 	gl_freevalue.freevalueid in\r\n" +
                "		\r\n" +
                "		(select freevalueid from gl_freevalue where freevalueid in (select zassid freevalueid from gl_assautoconfigslave0 slave\r\n" +
                "		inner join gl_assautoconfigmaster master on  master.pk_assautoconfigmaster = slave.pk_assautoconfigmaster\r\n" +
                "		where master.configtype=2  and slave.pk_accassoa='"+pk_accasoa+"')) ";
        IUAPQueryBS iuapQueryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        List<Map<String, Object>> freecalueList = (List<Map<String, Object>>) iuapQueryBS.executeQuery(sql, new MapListProcessor());
//    	        String sql2 ="select pid from bd_defdoc where pk_defdoc='"+pk_defdoc+"'";
//    	 		Map<String, Object> docmap = (Map<String, Object>) iuapQueryBS.executeQuery(sql2, new MapProcessor());
//    	 		String pid = docmap.get("pid")==null?"":docmap.get("pid").toString();

        boolean b=true;

        String assid="";

        boolean condition = true;

        do {
            String sql2 ="select pid from bd_defdoc where pk_defdoc='"+pk_defdoc+"'";
            Map<String, Object> docmap = (Map<String, Object>) iuapQueryBS.executeQuery(sql2, new MapProcessor());
            String pid="";
            if(docmap!=null) {
                pid = docmap.get("pid")==null?"":docmap.get("pid").toString();
            }
            for(Map<String, Object> map :freecalueList) {
                if(map.get("pk_defdoc")!=null) {
                    if(map.get("pk_defdoc").equals(pid)) {

                        condition=false;
                        assid = map.get("freevalueid").toString();
                    }
                }

            }


            pk_defdoc=pid;
            //	condition = 条件更新;


            if (!condition||pid.equals("")) {
                break;
            }
        } while (condition);











        return assid;


    }
    public Collection<AssautoconfigSlave0VO> getsalveVo(String pk_accasoa,String configtype,String pk_accountingbook,String version) throws BusinessException {
        //查找父类是否存在
        IUAPQueryBS iuapQueryBS = NCLocator.getInstance().lookup(IUAPQueryBS.class);
        String getFatherSql = "SELECT ount.pk_account,asoa.pk_accasoa,ount.pid,asoa1.pk_accasoa oa ,asoa.name\r\n" +
                "     			FROM bd_accasoa asoa \r\n" +
                "     			left join bd_account ount on ount.pk_account=asoa.pk_account\r\n" +
                "     			left join bd_accasoa asoa1 on asoa1.pk_account=ount.pid"
                + " where asoa.pk_accasoa='"+pk_accasoa+"'";

        Map<String, Object> map = (Map<String, Object>) iuapQueryBS.executeQuery(getFatherSql, new MapProcessor());
        //含有父级 并查询当前父级是否有配置过自动带出，如果有 返回 如果无则继续递归，直到pid为空
        configtype = "2";
        // if(map.get("oa")==null) {}
        String sql = " pk_accassoa='" + map.get("oa") + "' and pk_assautoconfigmaster in ( select pk_assautoconfigmaster from  gl_assautoconfigmaster where   configtype='" + configtype + "' and pk_accountingbook='" + pk_accountingbook + "' and asoaversion='" + version + "') ";

        Collection<AssautoconfigSlave0VO> slave0VOS2 = iuapQueryBS.retrieveByClause(AssautoconfigSlave0VO.class, sql);
        if (slave0VOS2 == null || slave0VOS2.size() == 0) {

            if(map.get("pid")==null) {
                return slave0VOS2;

            }
            if(slave0VOS2.size()!=0) {return slave0VOS2;}
            slave0VOS2= getsalveVo(map.get("oa").toString(),configtype,pk_accountingbook,version);


        }





        return slave0VOS2;


    }



}
